import {
  ClickModal,
  SearchFields,
  useCall,
  useEffectState,
  useReq,
  useSimpleMemo,
  useTableColumns,
} from '@/components';
import { TABLE_KEYS } from '@/constants/componentKeys';
import { forkHandler, pick } from '@/utils';
import { pull } from '@/utils/fp';
import { Empty, Table } from 'antd';
import * as PropTypes from 'prop-types';
import React, { forwardRef, lazy, useEffect, useRef, useState } from 'react';

const defaultFilter = () => true;
const defaultService = (values) => [values];
const defaultResult = (result) => result?.data?.records ?? [];
const defaultColumns = [{}];

const getSelected = (dataSource, rowKey, selected) => dataSource.filter((v) => selected.includes(v[rowKey]));
ModalSelectTable = forwardRef(ModalSelectTable);

function pushList(list, addList = []) {
  addList.forEach((item) => {
    if (!list.includes(item)) list.push(item);
  });
  return list;
}
function pullList(list, pullList = list) {
  pullList.forEach((item) => {
    while (list.includes(item)) {
      list.splice(list.indexOf(item), 1);
    }
  });
  return list;
}

function ModalSelectTable(props, ref) {
  const {
    service,
    fields,
    columns = defaultColumns,
    rowKey = 'id',
    selectType = 'radio',
    filter = defaultFilter,
    onService = defaultService,
    onResult = defaultResult,
    selectedKeys,

    onOk,
    onToggle,

    formLazy = false,
    ...rest
  } = props;

  const [selected = [], select] = useEffectState(selectedKeys);
  const xhr = useReq(service);
  const dataSource = useSimpleMemo(onResult(xhr.result).filter(filter));
  const invisibleKeys = useRef([]).current;

  const allData = useRef([]).current;
  useEffect(() => {
    if (!xhr.result) return;

    const allKeys = allData.map((v) => v[rowKey]);
    const pushItems = dataSource.filter((item) => !allKeys.includes(item[rowKey]));
    if (pushItems.length) allData.push(...pushItems);

    const dataKeys = dataSource.map((v) => v[rowKey]);
    select((selected = []) => {
      let list = selected;
      const invisible = selected.filter((v) => !dataKeys.includes(v));
      if (invisible.length) {
        pushList(invisibleKeys, invisible);
        list = pullList(selected.slice(), invisible);
      }
      const visible = invisibleKeys.filter((v) => dataKeys.includes(v));
      if (visible.length) {
        list = pushList(selected.slice(), visible);
        pullList(invisibleKeys, visible);
      }

      return list;
    });
  }, [dataSource]);

  /* useEffect(() => {
    service({}, { hideMsg: true }).then((all) => {
      const data = onResult(all).filter(filter)
      const allKeys = allData.map(v => v[rowKey])
      const pushItems = data.filter(item => !allKeys.includes(item[rowKey]))
      if (pushItems.length) allData.push(...pushItems)
    });
  }, []); */

  const [tableProps, modalProps] = useSimpleMemo(pick(rest, pull('title')(TABLE_KEYS)));
  const [xhrFired, setFired] = useState(false);

  const get = useCall((formData = {}) => {
    setFired(true);
    const args = onService(formData);
    xhr.start(...args);
  });

  const onSelect = useCall((selectKeys) => {
    select(selectKeys ?? selectedKeys ?? []);
  });

  const allKeys = [].concat(invisibleKeys, selected);
  const handleOk = useCall(() => {
    console.log({ allData, rowKey, allKeys });
    if (typeof onOk === 'function') return onOk(getSelected(allData, rowKey, allKeys));
  });

  const handleToggle = useCall(
    forkHandler(onToggle, (open) => {
      if (open) {
        setFired(false);
        if (!formLazy) get();
        pullList(invisibleKeys);
      }
    }),
  );

  // 模态框内容
  const content = (
    <>
      {(fields?.length ?? false) && (
        <SearchFields fields={fields} colProps={{ xs: 12 }} onSubmit={get} onReset={get} lazy={formLazy} />
      )}
      {formLazy && !xhrFired ? (
        <Empty description='请输入查询条件' />
      ) : (
        <Table
          pagination={false}
          size='small'
          scroll={{ y: 'max(240px, min(720px, calc(100vh - 540px)))' }}
          {...tableProps}
          dataSource={dataSource}
          columns={columns}
          loading={xhr.status === 'loading'}
          rowKey={rowKey}
          rowSelection={{
            ...tableProps.rowSelection,
            type: selectType,
            selectedRowKeys: selected,
            onChange: onSelect,
          }}
        />
      )}
    </>
  );

  return (
    <ClickModal
      ref={ref}
      {...modalProps}
      onOk={handleOk}
      okButtonProps={{ disabled: !allKeys.length }}
      onToggle={handleToggle}
      content={content}
    />
  );
}

ModalSelectTable.propTypes = {
  /** 列表请求 */
  service: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired,

  /** 列表请求字段 */
  fields: PropTypes.array,

  /** 表格列配置 */
  columns: PropTypes.array,

  /** 列表主键 */
  rowKey: PropTypes.string,

  /** 选择类型 */
  selectType: PropTypes.oneOf(['radio', 'checkbox']),

  /** 默认选中 */
  selectedKeys: PropTypes.arrayOf(PropTypes.string),

  /** 过滤数据 */
  filter: PropTypes.func,

  /** 表单值转为请求参数 */
  onService: PropTypes.func,

  /** 请求结果转为表格数据 */
  onResult: PropTypes.func,

  /** 确认事件 */
  onOk: PropTypes.func,
};

export default ModalSelectTable;
